package com.wing.web.common.interceptor;//package com.wing.interceptor;


import com.wing.common.constant.GlobalConstants;
import com.wing.common.constant.SecurityConstants;
import com.wing.web.db.config.util.DynamicDataSource;
import com.wing.web.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 接口拦截器
 *
 * @author
 */
@Component
@Slf4j
//public class InterfaceInterceptor implements HandlerInterceptor {
public class InterfaceInterceptor implements Filter {

    @Value("${database.prefix}")
    private String prefix;
    @Value("${database.ip}")
    private String address;
    @Value("${database.port}")
    private String port;
    @Value("${spring.datasource.druid.username}")
    private String username;
    @Value("${spring.datasource.druid.password}")
    private String password;

    private static Map<String,String> dsDomainMap=new HashMap<>();

    @Autowired
    private StringRedisTemplate redisTemplate;

//    @Override
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        log.info("拦截器....{},theadName:{},theadId:{}", request.getServletPath(),Thread.currentThread().getName(),Thread.currentThread().getId());
//
////        StringBuffer url = request.getRequestURL();
////        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getSession().getServletContext().getContextPath()).toString();
////        String domain = tempContextUrl.split("://")[1];
////        if(domain.indexOf(":") != -1){
////            domain = domain.split(":")[0];
////        }
//        if ("/user/admin/authority/authorityRoleList".equals(request.getServletPath())){
//            return true;
//        }
//        String domain=request.getHeader("domain");
//        if (domain==null){
//            String url=request.getRequestURL().toString();
//            int startIndex=url.indexOf("//")+2;
//            int endIndex=url.indexOf(":",startIndex);
//            String ip=url.substring(startIndex,endIndex);
//            if (ip.endsWith("madeinchina.ltd")){
//                domain=ip;
//            }
//
//        }
//        log.info("拦截器域名....{},theadName:{},theadId:{}", domain,Thread.currentThread().getName(),Thread.currentThread().getId());
//
//        // 微信小程序域名
//        String wxDomain = "xcx.madeinchina.ltd";
//        List<String> urlList = new ArrayList<>(); // 接口过滤集合
//        urlList.add("/user/app/user/loginByPhone");
//        urlList.add("/user/app/user/weChatLogin");
////        urlList.add("/system/admin/systemOfficialInfo/getInfo");
////        urlList.add("/user/admin/client/getByClientId");
////        urlList.add("/user/admin/user/getByUsername");
////        urlList.add("/user/admin/authority/authorityRoleList");
//        log.info("拦截手机号....{},theadName:{},theadId:{}", request.getParameter("phone"),Thread.currentThread().getName(),Thread.currentThread().getId());
//
//        if(domain.indexOf("madeinchina.ltd") != -1){ // 请求接口存在域名
//            if(domain.equals(wxDomain)){
//                // 截取不需要登录的接口
//                if(urlList.contains(request.getServletPath())){
//                    // 获取传过来的手机号参数
//                    String phone = request.getParameter("phone");
//                    // 查询手机号对应的数据源
//                    String database = queryDataSourceConfig(null, phone);
//                    log.info("query database by phone:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                    if(StringUtils.isNotBlank(database)){
//                        if(request.getServletPath().indexOf("/user") == 0||request.getServletPath().indexOf("/oauth2") == 0){
//                            DynamicDataSource.name.set("user-"+database);
//                        }else{
//                            DynamicDataSource.name.set(database);
//                        }
//                    }
//                }else{
//                    try {
//                        log.info("query database by token:{}",JwtUtils.getEnterpriseCode().toLowerCase());
//                        DynamicDataSource.name.set(JwtUtils.getEnterpriseCode().toLowerCase());
//                    } catch (Exception e) {
//                        log.info("1.该接口未传token; 2.如果该接口不需要token，请将接口加入到拦截器过滤集合中，接口拦截器(InterfaceInterceptor)，例子:(urlList.add(\"/user/admin/user/getByUsername\");)");
//                        return false;
//                    }
//                }
//            }else{
//                // 通过域名查询关联的数据库
//                String database = queryDataSourceConfig(domain, null);
//                log.info("query database by domain:{},theadName:{},theadId:{}",database);
//                if(StringUtils.isNotBlank(database)){
//                    if(request.getServletPath().indexOf("/user") == 0||request.getServletPath().indexOf("/oauth2") == 0){
//                        log.info("###################set user datasource key:{},theadName:{},theadId:{}",("user-"+database),Thread.currentThread().getName(),Thread.currentThread().getId());
//                        log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
//                        DynamicDataSource.name.set("user-"+database);
//                    }else{
//                        log.info("#################set enterprise datasource key:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                        log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
//                        DynamicDataSource.name.set(database);
//                    }
//                }
//            }
//        }else{
//
////            DynamicDataSource.name.set(JwtUtils.getEnterpriseCode());
//        }
//        return true;
//    }

    private String queryDataSourceConfig(String domain, String phone) {
//        String url = "jdbc:mysql://"+GlobalConstants.ADDRESS+":"+GlobalConstants.PORT+"/"+GlobalConstants.USER_PREFIX+"?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC&serverTimezone=Asia/Shanghai";
//        String username = GlobalConstants.USERNAME;
//        String password = GlobalConstants.PASSWORD;
        String url = "jdbc:mysql://"+address+":"+port+"/"+prefix+"-user"+"?characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC&serverTimezone=Asia/Shanghai";

        Connection newConn = null; // 连接刚刚创建的数据库
        String name = "";
        try {
            newConn = DriverManager.getConnection(url, username, password);
            Statement newSmt = newConn.createStatement();
            String sql = "";
            if(StringUtils.isNotBlank(domain)){
                sql = "select * from sys_data_source where domain = " + '"' + domain + '"';
                ResultSet resultSet = newSmt.executeQuery(sql);
                while (resultSet.next()){
                    name = resultSet.getString("name");
                }
            }else if(StringUtils.isNotBlank(phone)){
                sql = "select * from sys_phone_code where phone = " + '"' + phone + '"';
                ResultSet resultSet = newSmt.executeQuery(sql);
                while (resultSet.next()){
                    name = resultSet.getString("code");
                }
            }
            newSmt.close();
            newConn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return name;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        log.info("service拦截器***********************************************START");
        log.info("service拦截器....{},theadName:{},theadId:{}", request.getServletPath(),Thread.currentThread().getName(),Thread.currentThread().getId());

//        StringBuffer url = request.getRequestURL();
//        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getSession().getServletContext().getContextPath()).toString();
//        String domain = tempContextUrl.split("://")[1];
//        if(domain.indexOf(":") != -1){
//            domain = domain.split(":")[0];
//        }
        log.info("------------------path:{}",request.getServletPath());
        log.info("------------------url:{}",request.getRequestURL());
        if ("/user/admin/authority/authorityRoleList".equals(request.getServletPath())
                ||"/v3/api-docs".equals(request.getServletPath())
//                ||"/websocket/cabOpen".equals(request.getServletPath())
        ){
//            return true;

            filterChain.doFilter(servletRequest, servletResponse);

            return;
        }
        String domain=request.getHeader("domain");
        log.info("service拦截器域名....HEADER domain:{},theadName:{},theadId:{}", domain,Thread.currentThread().getName(),Thread.currentThread().getId());

        if (StringUtils.isBlank(domain)){
            String url=request.getRequestURL().toString();
            int startIndex=url.indexOf("//")+2;
            int endIndex=url.indexOf(":",startIndex);
            String ip=url.substring(startIndex,endIndex);
            log.info("###########################IP:{}",ip);
            if (ip.endsWith("xgongchang.cn") || ip.endsWith("yunduanzhizao.com")){
                domain=ip;
            }
            log.info("service拦截器域名....URL domain:{},theadName:{},theadId:{}", domain,Thread.currentThread().getName(),Thread.currentThread().getId());
        }

        // 微信小程序域名
        String wxDomain = "xcx.madeinchina.ltd";
        wxDomain="szgcxcx.yunduanzhizao.com";
        List<String> urlList = new ArrayList<>(); // 接口过滤集合
        urlList.add("/user/app/user/loginByPhone");
        urlList.add("/user/app/user/weChatLogin");
        urlList.add("/sms/admin/sendSmsCode");
        urlList.add("/oauth2/admin/user/login");
        urlList.add("/api/auth/oauth/token");
        urlList.add("/warehouse/admin/user/getByUsername");
//        urlList.add("/system/admin/systemOfficialInfo/getInfo");
//        urlList.add("/user/admin/client/getByClientId");
//        urlList.add("/user/admin/user/getByUsername");
//        urlList.add("/user/admin/authority/authorityRoleList");
        log.info("service拦截手机号....{},theadName:{},theadId:{}", request.getParameter("phone"),Thread.currentThread().getName(),Thread.currentThread().getId());

        if(StringUtils.isNotBlank(domain) && (domain.indexOf("xgongchang.cn") != -1 || domain.indexOf("yunduanzhizao.com") != -1)){ // 请求接口存在域名
            log.info("--------------------------domain:{},wxDomain:{}",domain,wxDomain);
            log.info("**************************domain if:{}",domain.equals(wxDomain));
            if(domain.equals(wxDomain)){
                // 截取不需要登录的接口
                log.info("-------------------urlList:{}",urlList.toString());
                log.info("-----------------servlet path:{}",request.getServletPath());
                log.info("************************url if:{}",urlList.contains(request.getServletPath()));
                if(urlList.contains(request.getServletPath())){
                    // 获取传过来的手机号参数
                    String phone = request.getParameter("phone");
                    log.info("**********************phone:{}",phone);
                    // 查询手机号对应的数据源
                    String database = null;
                    try{
                        database=redisTemplate.opsForValue().get(SecurityConstants.DS_PHONE_PREFIX+phone);
                        log.info("service拦截器GET DS KEY BY WX PHONE FROM REDIS###################ds key from redis:{}",database);
                        if (StringUtils.isBlank(database)){
                            database = queryDataSourceConfig(null, phone);
                            redisTemplate.opsForValue().set(SecurityConstants.DS_PHONE_PREFIX+phone,database);
                            log.info("service拦截器GET DS KEY BY WX PHONE FROM DB###################ds key from db:{}",database);
                        }
                    }catch (Exception e){
                        log.error("get database from redis fail",e);
                        try{
                            database = queryDataSourceConfig(null, phone);
                            redisTemplate.opsForValue().set(SecurityConstants.DS_PHONE_PREFIX+phone,database);
                            log.info("service拦截器GET DS KEY BY WX PHONE FROM DB###################ds key from db:{}",database);
                        }catch (Exception e2){
                            log.error("get database from db fail",e2);
//                            DynamicDataSource.name.set("core");
                            log.info("get database from db fail",e2);
                        }

                    }
                    log.info("service拦截器GET DS KEY BY WX PHONE ###################query database by phone:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
                    if(StringUtils.isNotBlank(database)){
                        if(request.getServletPath().indexOf("/user") == 0||request.getServletPath().indexOf("/oauth2") == 0||request.getServletPath().indexOf("/sms") == 0){
                            log.info("service拦截器SET DS KEY BY WX PHONE###################set user datasource key by phone(wx):{},theadName:{},theadId:{}",("user-"+database),Thread.currentThread().getName(),Thread.currentThread().getId());
//                            log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                            DynamicDataSource.name.set("user-"+database.toLowerCase());
                        }else{
                            log.info("service拦截器SET DS KEY BY WX PHONE#################set enterprise datasource key by phone(wx):{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                            log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                            DynamicDataSource.name.set(database.toLowerCase());
                        }
                    }else{
//                        DynamicDataSource.name.set("core");
                        log.info("database by phone is null ,domain:{},phone:{}",domain,phone);
                    }
                }else{
                    try {
                        log.info("query database by token:{}", JwtUtils.getEnterpriseCode().toLowerCase());
                        log.info("enterpriseCode:{},enterpriseId:{},enterpriseName:{}", JwtUtils.getEnterpriseCode(), JwtUtils.getEnterpriseId(), JwtUtils.getEnterpriseName());
                        log.info("service拦截器GET DS KEY BY WX TOKEN ###################set enterprise datasource key by token(wx):{},theadName:{},theadId:{}", JwtUtils.getEnterpriseCode().toLowerCase(),Thread.currentThread().getName(),Thread.currentThread().getId());
//                        log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                        String database= JwtUtils.getEnterpriseCode().toLowerCase();
//                        DynamicDataSource.name.set(JwtUtils.getEnterpriseCode().toLowerCase());
                        if(StringUtils.isNotBlank(database)){
                            if(request.getServletPath().indexOf("/user") == 0||request.getServletPath().indexOf("/oauth2") == 0||request.getServletPath().indexOf("/sms") == 0){
                                log.info("service拦截器SET DS KEY BY WX TOEKN#################set user datasource key by token(wx):{},theadName:{},theadId:{}",("user-"+database),Thread.currentThread().getName(),Thread.currentThread().getId());
//                                log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                                DynamicDataSource.name.set("user-"+database.toLowerCase());
                            }else{
                                log.info("service拦截器SET DS KEY BY WX TOEKN#################set enterprise datasource key by token(wx):{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                                log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                                DynamicDataSource.name.set(database.toLowerCase());
                            }
                        }

                    } catch (Exception e) {
                        log.info("1.该接口未传token; 2.如果该接口不需要token，请将接口加入到拦截器过滤集合中，接口拦截器(InterfaceInterceptor)，例子:(urlList.add(\"/user/admin/user/getByUsername\");)");
//                        return false;
//                        filterChain.doFilter(servletRequest, servletResponse);
//                        DynamicDataSource.name.set("core");
                        log.error("database by token fail,domain:{}",domain);
                    }
                }
            }else{
                // 通过域名查询关联的数据库
                String database = dsDomainMap.get(domain);
                log.info("service拦截器GET DS KEY BY DOMAIN FROM MAP#################get ds from map:{}",database);
                if (StringUtils.isBlank(database)){
                    database = queryDataSourceConfig(domain, null);
                    dsDomainMap.put(domain,database);
                    log.info("service拦截器SET DS KEY BY DOMAIN FROM DB QUERY###################get ds from db:{}",database);
                }
                log.info("query database by domain:{},theadName:{},theadId:{}",database);
                if(StringUtils.isNotBlank(database)){
                    if(request.getServletPath().indexOf("/user") == 0||request.getServletPath().indexOf("/oauth2") == 0||request.getServletPath().indexOf("/sms") == 0){
                        log.info("service拦截器SET DS KEY BY DOMAIN FROM MAP###################set user datasource key by domain:{},theadName:{},theadId:{}",("user-"+database),Thread.currentThread().getName(),Thread.currentThread().getId());
//                        log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                        DynamicDataSource.name.set("user-"+database.toLowerCase());
                    }else{
                        log.info("service拦截器SET DS KEY BY DOMAIN FROM MAP#################set enterprise datasource key by domain:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                        log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                        DynamicDataSource.name.set(database.toLowerCase());
                    }
                }else{
                    log.info("database by domain is null,database:{},domain:{}",database,domain);
//                    DynamicDataSource.name.set("core");
                }
            }
        }else{
            try{
//                if (JwtUtils.getEnterpriseCode()!=null){
                String database = "";
                if(!urlList.contains(request.getServletPath())){
                    database = JwtUtils.getEnterpriseCode().toLowerCase();
                    log.info("service拦截器TOKEN....TOKEN enterpriseCode:{},enterpriseId:{},enterpriseName:{}", JwtUtils.getEnterpriseCode(), JwtUtils.getEnterpriseId(), JwtUtils.getEnterpriseName());
                    log.info("#################set enterprise datasource key by token:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
                }
//                    log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
//                    DynamicDataSource.name.set(database);
                if(StringUtils.isNotBlank(database)){
                    log.info("service拦截器SET DS KEY BY TOEKN#################set enterprise datasource key by token:{},theadName:{},theadId:{}",database,Thread.currentThread().getName(),Thread.currentThread().getId());
//                    log.info("---------------------------set ds name:"+Thread.currentThread().getName()+","+Thread.currentThread().getId());
                    DynamicDataSource.name.set(database.toLowerCase());
                }

//                }

            }catch (Exception e){
                log.error("get token fail",e);
                log.info("1.该接口未传token; 2.如果该接口不需要token，请将接口加入到拦截器过滤集合中，接口拦截器(InterfaceInterceptor)，例子:(urlList.add(\"/user/admin/user/getByUsername\");)");
//                DynamicDataSource.name.set("core");
                log.info("get token fail",e);
            }

        }

        // 将域名作为属性放入请求中
        request.setAttribute("currentDomain", domain);
        log.info("service拦截器***********************************************END");
//        return true;
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {

    }
}
